require "observer"
require "socket"
require 'thread'
 
module PCLink
  
  class Listener 
    include Observable 
    
    def initialize(options)
      @options = options
      @port = @options[:port]
      @active = true
    end
    
    def start
      puts "starting listener on #{Thread.current}"
      @sock = TCPServer.new(@port)
      @sock.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1) 
      create_listener_thread
    end 
    
    def stop 
      @sock.close if @sock 
      @active = false
    end
    
    private 
    def create_listener_thread
      mutex = Mutex.new
      resource = ConditionVariable.new
      started = false
      # create a thread-per-connection
      Thread.new do
        while(@active)
          puts "listener started"
          mutex.synchronize {
            notify_listener_started(@sock.addr[2], @sock.addr[1])
            started = true
            resource.signal
          }
          s = @sock.accept
          puts "new connection from #{s.peeraddr[2]}:#{s.peeraddr[1]}"
          msg = ""
          while s.gets
            msg = msg + $_
          end
          s.close
          notify_message_received(msg)
        end
      end
      mutex.synchronize {
        resource.wait(mutex) if !started
      }
    end 
    
    def notify_message_received(msg)
      changed
      notify_observers({:message => msg})
    end
    
    def notify_listener_started(host, port)
      puts "notifying of listener start"
      changed
      notify_observers({:host => host, :port => port})
    end
  end

end